/*
	Interrupt Routing
*/
#include <stdint.h>
#include "kernel.h"
#include "it.h"
#include "iroute.h"
#include "heap.h"

iroute_jentry 	____iroute_jentry[256];
iroute_hook		*____iroute_hook[256];

void iroute_stub(uint32_t line)
{
	iroute_hook *ch;
	//kdbginfo("line was %x, first hook is %x\n", line, ____iroute_hook[line]);
	/// call any hooks present for line.
	for(ch = ____iroute_hook[line]; ch != 0; ch = (iroute_hook*)ch->next)
	{
		//kdbginfo("calling handler %x\n", ch->handler);
		ch->handler(line);
	}
	return;
}

int iroute_initialize()
{
	uint32_t x;
	//kdbginfo("creating jump table for interrupt descriptor table.\n");
	for(x = 0; x < 256; ++x)
	{
		____iroute_jentry[x].push = 0x60;
		____iroute_jentry[x].mov1 = 0xb8;
		____iroute_jentry[x].v1 = x;
		____iroute_jentry[x].mov2 = 0xbb;
		____iroute_jentry[x].v2 = (uintptr_t)&iroute_stub86;
		____iroute_jentry[x].jump = 0xe3ff;
		it_set(g_k_idt, x, (uintptr_t)&____iroute_jentry[x], 0x8, IT_PRESENT);
		____iroute_hook[x] = 0;
	}
	return 1;
}

int iroute_makehook(uint32_t line, iroute_hook_handler handler)
{
	/// check if hook already exists.
	iroute_hook *ch;
	kdbginfo("hook %x for line %x\n", (uint32_t)handler, line);
	/// call any hooks present for line.
	for(ch = ____iroute_hook[line]; ch != 0; ch = (iroute_hook*)ch->next)
	{
		if(ch->handler == handler)
		{
			return -1;
		}
	}
	ch = (iroute_hook*)kmalloc(sizeof(iroute_hook));
	ch->next = (struct Tiroute_hook*)____iroute_hook[line];
	ch->prev = 0;
	if(____iroute_hook[line] != 0)
	{
		____iroute_hook[line]->prev = ch;
	}
	____iroute_hook[line] = ch;
	ch->handler = handler;
	return 1;
}

